A locale pack is a .kzb file that contains only the resources of a specific locale. Using Kanzi Engine API you can load the application resources used by a certain locale only when you need them, and unload the resources that the application does not need. That way only the resources used by the current locale occupy the device memory.
In this step of the tutorial you first prepare the Kanzi Studio project for loading additional locales and create locale packs for Japanese and Chinese locales which contain only the resources used by each of those locales. You then use the Kanzi Engine API to load the locale packs when a user clicks a button in the Kanzi application.
In this section you make a few modifications to the Kanzi Studio project you created in the first two steps of the tutorial. You import fonts that support the locales you add in this step of the tutorial, prepare the project so that instances of the LocaleButton prefab in the LocaleSelector use a custom property to control the locale of the application, add a control for loading additional locales, and you create aliases that allow you to readily access the project nodes using the Kanzi Engine API.
To prepare the project for loading additional locales:
Note that in order to properly render text content you have to use a font that includes the glyphs of the languages you want to include in your Kanzi application.
Click Save.
You use this custom property type to set the locale using the buttons in the LocaleSelector node.
.
A locale pack is a .kzb file that contains only the resources of a specific locale.
In this section you add to the project localized resources for Japanese and Chinese locales, create styles which use the fonts that contain the glyphs of these locales, and create locale packs. In the next section you use the Kanzi Engine API to load the locale packs.
In the <KanziWorkspace>/Tutorials/Localization/Assets/Text you can find the .po files that contain all the text strings used in the Kanzi Studio project in this tutorial localized to Japanese and Chinese.
To create locale packs:
In Kanzi Studio select > Export KZB > Export Locale KZBs. This command:
Tip If you want to export the entire Kanzi Studio project to a single .kzb file, including the resources of locales you mark as locale packs, select > Export KZB > Export KZB Binary.
In this section you use the Kanzi Engine API to load the locale packs you created in the previous section. The application loads the locale packs when a user clicks the LoadLocales button you created in the beginning of this tutorial step, and triggers the loading of the locale packs for all locales stored in the <KanziWorkspace>/Projects/<ProjectName>/Application/bin/Locale_packs directory.
To load the locale packs:
jp-JP.kzb zh-Hans.kzb
fstream
so that you can read the binaries.cfg file that contains the list of additional locales.#include <fstream>
DynamicPropertyType
and use the same name that is used in the Kanzi Studio project.class LocalizationApplication: public ExampleApplication
{
...
// Type of the shared pointer for the custom property type defined
// in the Kanzi Studio project.
typedef std::shared_ptr<DynamicPropertyType<std::string> > StringDynamicPropertyTypeSharedPtr;
LocalizationApplication
class after the onProjectLoaded
function implement the onLoadAdditionalLocalesButtonClicked
event handler for the Button 2D click message from the LoadLocales node.void onLoadAdditionalLocalesButtonClicked(Button2D::ClickedMessageArguments& /*messageArgs*/)
{
// Set the name of the directory where you stored the locale packs.
static const std::string localizationFolderName = "Locale_packs";
// Get the Screen node in the .kzb binary. You use the Screen node to access
// all the other nodes and resources in the .kzb binary.
ScreenSharedPtr screen = getScreen();
// Domain is a collection of all subsystems and contains the Kanzi resource manager.
// You need to get the resource manager to access the resources in the .kzb file.
ResourceManager* resourceManager = getDomain()->getResourceManager();
// Get the LocaleSelector node which contains the locale selection buttons.
Node2DSharedPtr localeSelector = screen->lookupNode<Node2D>("#LocaleSelector");
// Get the LocaleButton prefabricated template used for the buttons that set the locale.
// Get the reference to the template using the .kzb URL.
// When you use the full path of a resource, start the path with kzb://
followed by the project name and the location of the resource.
PrefabTemplateSharedPtr localeButtonPrefab = resourceManager->
acquireResource<PrefabTemplate>("kzb://localization/Prefabs/LocaleButton");
// Get the custom property type for setting the name of the locale in the
// LocaleButton node. You created this custom property type in the Kanzi Studio project.
StringDynamicPropertyTypeSharedPtr localeNameProperty =
StringDynamicPropertyTypeSharedPtr(new DynamicPropertyType<std::string>("LocaleName"));
// Get the custom property type for setting the locale in the application.
// You created this custom property type in the Kanzi Studio project.
StringDynamicPropertyTypeSharedPtr localeIdProperty =
StringDynamicPropertyTypeSharedPtr(new DynamicPropertyType<std::string>("LocaleID"));
// Read the binaries.cfg file that contains the list of the .kzb files
// that contain the locale packs.
std::string configFileName = localizationFolderName + "/binaries.cfg";
std::ifstream binariesConfigFileStream(configFileName.c_str());
std::string binaryFileName;
// Load the resources stored in the locale pack .kzb files.
while (getline(binariesConfigFileStream, binaryFileName))
{
// Create the path for the .kzb file.
std::string localizationKzbFilePath = localizationFolderName + "/" + binaryFileName;
// Add the .kzb file to the Kanzi resource manager.
KzuBinaryDirectory* binaryDirectory =
resourceManager->addDirectoryFromFile(localizationKzbFilePath);
// Load the locale resources from the .kzb file.
Screen::LocaleContainer locales = screen->registerLocales(*binaryDirectory);
// For each loaded locale pack add a button to the LocaleSelector node
// When you click the button, you change the application locale to the
// locale defined by the LocaleID property.
for (Screen::LocaleContainer::const_iterator it = cbegin(locales),
end = cend(locales); it != end; ++it)
{
std::string localeId = it->first;
ResourceDictionarySharedPtr localeDictionary = it->second;
// Instantiate the LocaleButton prefab.
Node2DSharedPtr localeButton =
localeButtonPrefab->instantiate<Node2D>("LocaleButton_" + localeId);
// Get the name of the locale that is shown in the application from the
// resource ID LocaleDisplayName stored in the localization table in the locale pack.
TextResourceSharedPtr localeDisplayNameResource =
localeDictionary->acquire<TextResource>(ResourceID("LocaleDisplayName"));
// Set the LocaleName property so that the Text Block 2D node in the button shows the name of the locale.
localeButton->setProperty(*localeNameProperty, localeDisplayNameResource->getText());
// Set the LocaleID property so that when you click the button the application changes to that locale.
localeButton->setProperty(*localeIdProperty, localeId);
// Set the style of the Text Block 2D node in the button so that it sets
// the correct font for the LocaleDisplayName of the locale.
// Use this approach only to apply a style from the locale pack without changing the locale
// in the application.
optional<string> localeStyle = localeDictionary->find(ResourceID("LocaleStyle"));
localeButton->setStyleResourceID(ResourceID(*localeStyle));
// Add the LocaleButton node to the LocaleSelector node.
localeSelector->addChild(localeButton);
}
}
// After loading the locales from the locale packs, hide the button for
// loading the locale packs.
Button2DSharedPtr loadAdditonalLanguagesButton =
screen->lookupNode<Button2D>("#LoadLocales");
loadAdditonalLanguagesButton->setVisible(false);
}
LocalizationApplication
class in the onProjectLoaded
function get the button that contains the trigger that loads locale packs and register the event handler for the Button: Click message of the button.virtual void onProjectLoaded() KZ_OVERRIDE { ... // Get the LoadLocales Button 2D node for loading additional locales. Button2DSharedPtr LoadLocalesButton = getScreen()-> lookupNode<Button2D>("#LoadLocales"); // Register the message handler for the Button: Click message used by the // LoadLocales node. LoadLocalesButton->addMessageFilter(Button2D::ClickedMessage, std::bind(&LocalizationApplication::onLoadAdditionalLocalesButtonClicked, this, std::placeholders::_1));
In this tutorial you learned how to localize Kanzi applications and use in your applications additional .kzb files that contain only localized resources for locales. To take this tutorial further, you can use the localization table .pot template to translate the content of this Kanzi application to additional languages. Additionally, you can create other resource types and create different resources for different locales. For example, create several animations and use each for a different locale:
To find out more about how to localize your Kanzi applications, see Localization.
To learn about how Kanzi handles resources, see Resource management.
To learn more about how to use resource dictionaries, see Resources.
To learn more about managing your Kanzi Studio projects, see Projects.
To learn more about creating Kanzi applications, see Tutorials.
To find out more about Kanzi Studio features, see Working with ....